﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using QAPro.Test.Addin.Fitnesse;
using QAPro.Test.FitServices.Interfaces;
using QAPro.Test.Interfaces;
using WiseLight.Framework.Lite.Container;

namespace QAPro.Test.Addin.FitnesseUI
{
    public partial class FitnesseWidgetUserControl : UserControl, IFitnesseWidgetUI
    {
        private readonly BindingList<FitEditableLocalTestPage> _testableItems =
            new BindingList<FitEditableLocalTestPage>();

        private readonly IList<ITestNode> _testedItems = new List<ITestNode>();
        private IFitTestEngine _fitTestEngine;
        private IFitUtilService _fitUtilService;
        private IFitLocalTestScriptProvider _scriptProvider;
        private IServiceContext _serviceContext;


        public FitnesseWidgetUserControl()
        {
            InitializeComponent();
            _serviceContext = new ServiceContext();
            RegisterServices(_serviceContext);
        }

        private IFitUtilService FitUtilityService
        {
            get
            {
                if (_fitUtilService == null)
                    _fitUtilService = _serviceContext.Services.Get<IFitUtilService>();
                return _fitUtilService;
            }
        }

        #region IFitnesseWidgetUI Members

        public string AddinName
        {
            get { return "Fitnesse Widget 1.0"; }
        }

        public string CommandLineOptionName
        {
            get { throw new NotImplementedException(); }
        }

        public IList<ITestNode> TestedItems
        {
            get { return _testedItems; }
        }


        public bool ExitOnTestFail
        {
            get { throw new NotImplementedException(); }
        }

        public bool ValidateAddinParameters(string param, ref string validationResult)
        {
            return true;
        }

        public void RegisterServices(IServiceContext serviceContext)
        {
            serviceContext.Services.AddService<IFitTestEngine>(typeof (FitTestEngine));
            serviceContext.Services.AddService<IFitUtilService>(typeof (FitUtilService));
            serviceContext.Services.AddService<IFitLocalTestScriptProvider>(typeof (FitLocalTestScriptProvider));
            serviceContext.Services.AddService<ISuite>(typeof (FitLocalSuite));
            serviceContext.Services.AddService<ITestCase>(typeof (FitEditableLocalTestPage));
            serviceContext.Services.AddService<ITestLink>(typeof (FitIncludePage));
            serviceContext.Services.AddService<IFixtureTable>(typeof (FitFixtureTable));
            serviceContext.Services.AddService<IFixtureTextData>(typeof (FitFixtureTextData));
            serviceContext.Services.AddService<ITestReportWriter>(typeof (TestReportDisplay));
            serviceContext.Services.AddService<IFixtureResult>(typeof (FitFixtureResult));
            serviceContext.Services.AddService<ITestFrameworkAddin>(this);
        }

        public ITestScriptProvider GetScriptProvider()
        {
            if (_scriptProvider == null)
            {
                _scriptProvider = _serviceContext.Services.Get<IFitLocalTestScriptProvider>("A Test Session",
                                                                                            toolStripTextBoxRunPath.Text);
                _scriptProvider.OnAfterCreateNode += OnAfterCreateNode;
            }
            return _scriptProvider;
        }

        public ITestEngine GetTestEngine()
        {
            if (_fitTestEngine == null)
            {
                _fitTestEngine = _serviceContext.Services.Get<IFitTestEngine>();
                _fitTestEngine.OnTestComplete += OnTestComplete;
            }

            return _fitTestEngine;
        }

        public void RunSilent(string runPath, string testCaseName)
        {
            _serviceContext = new ServiceContext();
            RegisterServices(_serviceContext);
            toolStripTextBoxRunPath.Text = runPath;
            ReloadTestCases();
            FitEditableLocalTestPage item =
                _testableItems.SingleOrDefault(x => (string.Compare(x.Name, testCaseName, true) == 0));
            if (item != null)
            {
                listBoxTestCases.SelectedItem = item;
                toolStripButtonRun_Click(this, null);
            }
            else
                MessageBox.Show("Can not locate the test case to run :" + testCaseName);
        }

        public void Run()
        {
            _serviceContext = new ServiceContext();
            RegisterServices(_serviceContext);
            //ShowDialog();
        }

        public ITestReportWriter GetReportWriter()
        {
            return _serviceContext.Services.Get<ITestReportWriter>();
        }

        #endregion

        public void ReloadTestCases()
        {
            _testedItems.Clear();
            listBoxTestCases.DataSource = null;
            listBoxTestCases.Items.Clear();
            listBoxTestCases.DataSource = bindingSource1;
            EnableOnSelectTest(false);
            _scriptProvider = null;
            try
            {
                listBoxTestCases.BeginUpdate();
                progressBar.Visible = true;
                progressBar.Value = 0;
                GetScriptProvider().LoadScripts();
            }
            finally
            {
                listBoxTestCases.EndUpdate();
                progressBar.Visible = false;
            }

            IList<ITestNode> list = FitUtilityService.GetRunnableTest(toolStripTextBoxRunPath.Text, GetScriptProvider());
            _testableItems.Clear();
            foreach (FitEditableLocalTestPage test in list.OrderBy(x => x.Name))
                _testableItems.Add(test);
            bindingSource1.DataSource = _testableItems;
            listBoxTestCases.DataSource = bindingSource1;
            listBoxTestCases.DisplayMember = "Name";
            textBoxEditScript.DataBindings.Clear();
            textBoxEditScript.DataBindings.Add("Text", listBoxTestCases.DataSource, "EditText");

            textBoxName.DataBindings.Clear();
            textBoxName.DataBindings.Add("Text", listBoxTestCases.DataSource, "Name");

            webBrowserView.DataBindings.Clear();
            webBrowserView.DataBindings.Add("DocumentText", listBoxTestCases.DataSource, "TestHtml");
            if (list.Count != 0)
                EnableOnSelectTest(true);
        }

        private void toolStripButtonBrowse_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.SelectedPath = toolStripTextBoxRunPath.Text;
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                toolStripTextBoxRunPath.Text = folderBrowserDialog1.SelectedPath;
                ReloadTestCases();
            }
        }

        private void toolStripButtonRefresh_Click(object sender, EventArgs e)
        {
            ReloadTestCases();
        }

        private void EnableOnSelectTest(bool bEnable)
        {
            tabControlTestCase.Enabled = bEnable;
        }

        private void OnAfterCreateNode(ITestNode node)
        {
            if (node.GetType().GetInterfaces().Contains((typeof (ITestCase))))
            {
                progressBar.PerformStep();
            }
        }


        private void OnTestComplete(ITestNode node)
        {
            tabControlMain.SelectedIndex = 2;
        }

        private void toolStripButtonRun_Click(object sender, EventArgs e)
        {
            var testableItem = listBoxTestCases.SelectedItem as FitEditableLocalTestPage;
            if (testableItem == null)
            {
                MessageBox.Show("Select a test on the list");
                return;
            }
            GetTestEngine().Run(testableItem);
            (GetReportWriter() as TestReportDisplay).TestedItem = testableItem;
            GetReportWriter().GenerateReport();
            webBrowserResult.DocumentText = (GetReportWriter() as TestReportDisplay).ResultHtml;
            textBoxExceptions.Text = testableItem.TestResult.Exceptions.ToString();
            textBoxPass.Text = testableItem.TestResult.Right.ToString();
            textBoxFail.Text = testableItem.TestResult.Wrong.ToString();
            _testedItems.Add(testableItem);
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            RunTextPad();
        }

        public void RunTextPad()
        {
            string tempFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Temp\\";
            FitEditableLocalTestPage testableItem = FitEditableLocalTestPage.RunTest(tempFolder, _serviceContext,
                                                                                     textBoxTextPad.Text);
            textBoxExceptions.Text = testableItem.TestResult.Exceptions.ToString();
            textBoxPass.Text = testableItem.TestResult.Right.ToString();
            textBoxFail.Text = testableItem.TestResult.Wrong.ToString();
            webBrowserResult.DocumentText = testableItem.ResultHtml;
            tabControlMain.SelectedIndex = 2;
        }
    }
}